
#include <wchar.h>

int obex_mtu = 0;

byte obex_data[1024];

int rx_file_fd;

byte obex_state = 0;

byte obex_filename[100] = "/var/mobile/OBEX/";	

unsigned long int total_bytes_received = 0;
unsigned long int total_bytes_expected = 0;


int obex_parse_header(byte * data) {

	int return_val = 0;
	int name_len;

	int i;

	if (data[0] == 0x01) {
		// parse filename from current header
#ifdef DEBUG_MED
		printf("obex: parsing obex_filename...\n");
#endif
		name_len = (data[1] << 8) + (data[2]); 

		for(i = 0 ; i < ((name_len-3)/2-1) ; i++){
			obex_filename[i+17] = (data[(2*i)+3] << 8) + (data[(2*i)+4]);
		}
  		obex_filename[i+17] = 0;
#ifdef DEBUG_HIGH
		printf("obex: obex_filename = %s \n", obex_filename);
#endif
		if((rx_file_fd = open((const char *)obex_filename, O_RDWR | O_CREAT, 511)) == -1){
			printf("Error opening file, %s\n",strerror(errno));
		}

		if (lib_threaded == 1) {
			if (lib_callbacks->obex_start != NULL) {
				lib_callbacks->obex_start(obex_filename);
			}
		}

		return_val = name_len;
	}
	if (data[0] == 0xc3) {
		// parse file length from current header 
#ifdef DEBUG_MED
		printf("obex: parsing file length...\n");
#endif

		//convert file length to a 32 bit integer -- this is *just* the file len not, no headers included
		total_bytes_expected = (data[1] << 24) + (data[2] << 16) + (data[3] << 8)  + (data[4]);
		total_bytes_received = 0;
#ifdef DEBUG_MED
		printf("obex: file length = %d \n", (int) total_bytes_expected);
#endif
		return_val = 5;
	}

	// TODO: include other header parsings?
	//
	return return_val;
}


/*-----------------------------------------------------------------------------------*/
/*
 * obex_rfcomm_input():
 *
 * Called by RFCOMM when obex data has been received.
 */
/*-----------------------------------------------------------------------------------*/
err_t
obex_rfcomm_input(void *arg, struct rfcomm_pcb *pcb, struct pbuf *p, err_t err) {

	int num_bytes_out = 0;

	int packet_len;

	int num_bytes;
	int num_total_bytes = 0;

	struct pbuf *t; 

	byte * payload_data;

#ifdef DEBUG_LOW
	printf("inside obex_rfcomm_input... payload[0] = %d \n", ((u8_t *)p->payload)[0]);
#endif
	switch(((u8_t *)p->payload)[0]){
 
 		case 0x86:      
	
#ifdef DEBUG_MED
			printf("obex: responding with generic yes (?) command ...\n");
#endif
			// generic yes command
			obex_data[0] = 0xa0;
			obex_data[1] = 0x00;
			obex_data[2] = 0x07;
			obex_data[3] = 0x10;
			obex_data[4] = 0x00;
			obex_data[5] = 0x04;
			obex_data[6] = 0x00;
			num_bytes_out = 7;	
			//num_bytes_out = 0;	
			break;

		case 0x81:
			//disconnect request
#ifdef DEBUG_MED
			printf("obex: a disconnect request has been made: disconnecting...\n");
#endif
			obex_data[0] = 0xa0;
			obex_data[1] = 0x00;
			obex_data[2] = 0x03;
			num_bytes_out = 3;	

			if (lib_threaded == 1) {
				if (lib_callbacks->obex_done != NULL) {
					lib_callbacks->obex_done();
				}
			}

       		        break;

		case 0x02:
			// put request 
#ifdef DEBUG_MED
			printf("\n\tOBEX: Put request: len: 0x%02x%02x\n",
				((u8_t *)p->payload)[1],((u8_t *)p->payload)[2]);
#endif

			// Send paylod for header parsing
			payload_data = &(((u8_t *)p->payload)[3]);
			num_bytes = 1;

			while ((payload_data[0] != 0x48) & (payload_data[0] != 0x49) & (num_bytes > 0)) {
//			while ((payload_data[0] != 0x48) & (payload_data[0] != 0x49)) {

				num_bytes = obex_parse_header(payload_data);
				num_total_bytes = num_total_bytes + num_bytes;

				// Advance to next header
				payload_data = &(payload_data[num_bytes]);
			}


			if (num_bytes == 0) {
				//send the correct response back... this is probably going to be wrong...
				//obex_data[0] = 0xa0;
				obex_data[0] = 0x90;
				obex_data[1] = 0x00;
				obex_data[2] = 0x03;
				num_bytes_out = 3;	
				break;
			} 
	
			if (payload_data[0] == 0x49) {
#ifdef DEBUG_LOW
				printf("    obex: reached end of body....");
#endif
			}
	
			num_total_bytes = num_total_bytes + 3;

			packet_len  = (p->len) - (3+num_total_bytes);
			if((write(rx_file_fd, &((u8_t *)p->payload)[3 + num_total_bytes], packet_len)) != packet_len){
				printf("Error writing to file, %s\n",strerror(errno));
			} 
			total_bytes_received = total_bytes_received + packet_len;

			t = p; 
			while (t->next != NULL) {
#ifdef DEBUG_MED
				printf("  obex: writing next payload to obex file (for continued segments)...\n");
#endif
				t = t->next;
				packet_len  = (t->len);

				if((write(rx_file_fd, ((u8_t *)t->payload), packet_len)) != packet_len){
					printf("Error writing to file, %s\n",strerror(errno));
				}
				total_bytes_received = total_bytes_received + packet_len;
			}

			if (lib_threaded == 1) {
				if (lib_callbacks->obex_packet_receive != NULL) {
					lib_callbacks->obex_packet_receive(total_bytes_received, total_bytes_expected);
				}
			}

			if (total_bytes_received == total_bytes_expected) {
				close(rx_file_fd);
				total_bytes_received = 0;
				total_bytes_expected = 0;
			}
       
			//send the correct response back... this should be for continuation 
			obex_data[0] = 0x90;
			//obex_data[0] = 0xa0;
			obex_data[1] = 0x00;
			obex_data[2] = 0x03;
			num_bytes_out = 3;	
       
			break;

		case 0x82:
			// final put request 
#ifdef DEBUG_MED
			printf("\n\tOBEX: Put request (final): len: 0x%02x%02x\n",
				((u8_t *)p->payload)[1],((u8_t *)p->payload)[2]);
#endif

			// Send paylod for header parsing
			payload_data = &(((u8_t *)p->payload)[3]);
                        num_bytes = 1;

			while ((payload_data[0] != 0x48) & (payload_data[0] != 0x49) & (num_bytes > 0)) {
			//while ((payload_data[0] != 0x48) & (payload_data[0] != 0x49)) {

				num_bytes = obex_parse_header(payload_data);
				num_total_bytes = num_total_bytes + num_bytes;

				// Advance to next header
				payload_data = &(payload_data[num_bytes]);
			}

			if (num_bytes == 0) {
				//send the correct response back... this is probably going to be wrong...
				obex_data[0] = 0xa0;
				obex_data[1] = 0x00;
				obex_data[2] = 0x03;
				num_bytes_out = 3;	
				break;
			}

			if (payload_data[0] == 0x49) {
#ifdef DEBUG_MED
				printf("    reached end of body....\n");
#endif
			}
	
			num_total_bytes = num_total_bytes + 3;

			packet_len  = (p->len) - (3+num_total_bytes);
			if((write(rx_file_fd, &((u8_t *)p->payload)[3 + num_total_bytes], packet_len)) != packet_len){
				printf("Error writing to file, %s\n",strerror(errno));
			} 
			total_bytes_received = total_bytes_received + packet_len;

			t = p; 
			while (t->next != NULL) {
#ifdef DEBUG_MED
				printf("  writing next payload to obex file (for continued segments)...\n");
#endif
				t = t->next;
				packet_len  = (t->len);

				if((write(rx_file_fd, ((u8_t *)t->payload), packet_len)) != packet_len){
					printf("Error writing to file, %s\n",strerror(errno));
				}
				total_bytes_received = total_bytes_received + packet_len;
			}

			if (lib_threaded == 1) {
				if (lib_callbacks->obex_packet_receive != NULL) {
					lib_callbacks->obex_packet_receive(total_bytes_received, total_bytes_expected);
				}
			}

			if (total_bytes_received == total_bytes_expected) {
#ifdef DEBUG_HIGH
				printf("obex: closing file...\n");
#endif
				close(rx_file_fd);
				total_bytes_received = 0;
				total_bytes_expected = 0;
			}
       
			//send the correct response back... this is probably going to be wrong...
			obex_data[0] = 0xa0;
			obex_data[1] = 0x00;
			obex_data[2] = 0x03;
			num_bytes_out = 3;	
       
      
			break;
      
		case 0x80:
			//connect request, send connect response
#ifdef DEBUG_MED
			printf("OBEX CONNECT: 0x%02x\n",((u8_t *)p->payload)[0]);
#endif
			obex_mtu = (((u8_t *)p->payload)[5] << 8) | ((u8_t *)p->payload)[6];

#ifdef DEBUG_LOW
			printf("MAXIMUM TRANSMISSION UNIT: %d \n", obex_mtu);
#endif
			obex_data[0] = 0xa0;
			obex_data[1] = 0x00;
			obex_data[2] = 0x07;
			obex_data[3] = 0x10;
			obex_data[4] = 0x00;
			obex_data[5] = 0x04;
			obex_data[6] = 0x00;
			num_bytes_out = 7;	
               
			if (lib_threaded == 1) {
				if (lib_callbacks->obex_transfer_request != NULL) {
					lib_callbacks->obex_transfer_request();
				}
			}

			break;
       
		default:
			// Check if a packet came in and we are expecting more data
			if (total_bytes_received < total_bytes_expected) {
#ifdef DEBUG_MED
				printf("obex: processing the next chunk of data from the next rfcomm packet (not the start of an obex packet)....\n");
#endif
				packet_len  = (p->len);
//                       	printf("packet_len = %d \n", packet_len);
				if((write(rx_file_fd, ((u8_t *)p->payload), packet_len)) != packet_len){
					printf("Error writing to file, %s\n",strerror(errno));
				} 
				total_bytes_received = total_bytes_received + packet_len;

				t = p; 
				while (t->next != NULL) {
#ifdef DEBUG_MED
					printf("  obex: writing next payload to obex file (for continued segments)...\n");
#endif
					t = t->next;
       					printf("t->len = %d \n", t->len);
					packet_len  = (t->len);
                        		printf("packet_len = %d \n", packet_len);

					if((write(rx_file_fd, ((u8_t *)t->payload), packet_len)) != packet_len){
						printf("Error writing to file, %s\n",strerror(errno));
					}
					total_bytes_received = total_bytes_received + packet_len;
				}

				if (lib_threaded == 1) {
					if (lib_callbacks->obex_packet_receive != NULL) {
						lib_callbacks->obex_packet_receive(total_bytes_received, total_bytes_expected);
					}
				}

				if (total_bytes_received == total_bytes_expected) {
#ifdef DEBUG_MED
					printf("obex: closing file...\n");
#endif
					close(rx_file_fd);
					total_bytes_received = 0;
					total_bytes_expected = 0;
				}
			}
			break;  
	}

	// okay, now free up the physical buffer used for input before responding
	if (p->next != NULL) {
		if (p->next->next != NULL) {
			pbuf_free(p->next->next);
		}
		pbuf_free(p->next);
	}
	pbuf_free(p);

	// send obex data through rfcomm resposne if needed
	if (num_bytes_out > 0) {
		our_rfcomm_output(obex_data, num_bytes_out);
	}

	return ERR_OK;
}

